package com.winhxd.b2c.order.service.impl;

import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.Lock;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.context.AdminUser;
import com.winhxd.b2c.common.context.UserContext;
import com.winhxd.b2c.common.domain.order.condition.OrderAfterSaleCompleteCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderAfterSaleCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderExpressCondition;
import com.winhxd.b2c.common.domain.order.enums.*;
import com.winhxd.b2c.common.domain.order.model.OrderAfterSaleDetail;
import com.winhxd.b2c.common.domain.order.model.OrderExpressInfo;
import com.winhxd.b2c.common.domain.order.model.OrderLog;
import com.winhxd.b2c.common.domain.order.vo.OrderExpressInfoVO;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.order.dao.OrderAfterSaleDetailMapper;
import com.winhxd.b2c.order.dao.OrderExpressInfoMapper;
import com.winhxd.b2c.order.dao.OrderLogMapper;
import com.winhxd.b2c.order.service.OrderAfterSaleDetailService;
import com.winhxd.b2c.order.service.OrderExpressService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
 * @author:zhangyanwei
 * @date:2019/1/10 20:55:21
 * @Description:物流接口实现类
 **/
@Service
public class OrderExpressServiceImpl implements OrderExpressService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderExpressServiceImpl.class);
    private static final Integer UPDATE_SUCCESS = 1;
    /**
     * 类型：换货
     */
    private static final Integer EXCHANGE_TYPE = 3;
    /**
     * 类型：退货
     */
    private static final Integer RETURNING_TYPE = 2;
    /**
     * 已发货换货
     */
    private static final int DELIVERED_EXCHANDE = 3;
    /**
     * 已完成换货
     */
    private static final int FINISHED_EXCHANDE = 6;

    private static final int ORDER_UPDATE_LOCK_EXPIRES_TIME = 5000;
    private static final int AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME = 2000;

    @Autowired
    private Cache cache;

	@Resource
	private OrderAfterSaleDetailService orderAfterSaleDetailService;

    @Autowired
    private OrderExpressInfoMapper expressInfoMapper;

    @Autowired
    private OrderAfterSaleDetailMapper orderAfterSaleDetailMapper;

    @Autowired
    private OrderAfterSaleDetailMapper afterSaleDetailMapper;

    @Autowired
    private OrderLogMapper orderLogMapper;

    @Override
    public Integer saveExpress(OrderExpressInfo expressInfo) {
        return expressInfoMapper.insertSelective(expressInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveExpress4Exchange(OrderExpressCondition condition) {
        String lockKey = CacheName.CACHE_KEY_MODIFY_AFTER_SALE+condition.getOrderNo();
        if(null != condition.getSkuId()) {
            lockKey+=condition.getSkuId();
        }
        Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME);
        if (lock.tryLock()) {
            try {
                //校验该售后是否被手动关闭
                orderAfterSaleDetailService.validateCloseAfterSaleStatus(condition.getAfterSaleDetailId());
                //校验换货时，该售后单是否处于换货中
                OrderAfterSaleDetail info = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getAfterSaleDetailId());
                if(null != info && info.getViewStatus().intValue()!= AfterSaleViewStatusEnum.EXCHANGING.getTypeCode().intValue()){
                   throw new BusinessException(BusinessCode.CODE_460011);
                }
                String log="保存物流信息OrderExpressServiceImpl--";
                LOGGER.info(log + "售后换货保存物流信息开始");
                OrderExpressInfo expressInfo = new OrderExpressInfo();
                this.buildExpressProperty(condition,expressInfo);
                //保存物流信息
                Integer expressRes = expressInfoMapper.insertSelective(expressInfo);
                if(expressRes < UPDATE_SUCCESS){
                    throw new BusinessException(BusinessCode.CODE_460005);
                }
                //更改售后详细信息
                LOGGER.info(log + "更改售后详细信息开始");
                this.updateAfterSaleDetail(condition);
                //修改订单信息
                LOGGER.info(log + "修改订单信息开始");
                orderAfterSaleDetailService.updateOrderStatus(condition.getOrderNo());
                //保存日志信息
                LOGGER.info(log + "保存日志信息开始");
                OrderLog orderLog = new OrderLog();
                this.buildOrderLog(orderLog, condition);
                this.saveOrderLog(orderLog);
            } finally {
                lock.unlock();
            }
        }else {
            throw new BusinessException(BusinessCode.CODE_440603);
        }
        return UPDATE_SUCCESS;
    }

    /**
     * 构造物流信息
     * @param condition
     * @param expressInfo
     */
    private void buildExpressProperty(OrderExpressCondition condition, OrderExpressInfo expressInfo){
        LOGGER.info("物流信息入参：" + JsonUtil.toJSONString(condition));
        BeanUtils.copyProperties(condition,expressInfo);
        Date now = new Date();
	    expressInfo.setSendUser(condition.getSendUser());
	    expressInfo.setCreatedBy(condition.getSendUser());
	    expressInfo.setUpdatedBy(condition.getSendUser());
        expressInfo.setType(EXCHANGE_TYPE);
        expressInfo.setSendTime(now);
        expressInfo.setCreated(now);
        expressInfo.setUpdated(now);
        LOGGER.info("物流信息实体：" + JsonUtil.toJSONString(expressInfo));
    }

    /**
     * 根据售后ID修改售后状态
     * @param expressCondition
     */
    private void updateAfterSaleDetail(OrderExpressCondition expressCondition){
        OrderAfterSaleCompleteCondition condition = new OrderAfterSaleCompleteCondition();
        this.buildOrderAfterSaleComplete(expressCondition,condition);
        orderAfterSaleDetailMapper.updateCompleteStatusByCondition(condition);
    }

    /**
     * 构造售后完成入参
     * @param expressCondition
     * @param condition
     */
    private void buildOrderAfterSaleComplete(OrderExpressCondition expressCondition,OrderAfterSaleCompleteCondition condition){
        condition.setAfterSaleDetailID(expressCondition.getAfterSaleDetailId());
        condition.setCompleteStatus(AfterSaleCompleteStatusEnum.COMPLETED.getTypeCode());
        condition.setViewStatus(AfterSaleViewStatusEnum.EXCHANGED.getTypeCode());
        Date now = new Date();
        condition.setCompleteTime(now);
		condition.setUpdatedBy(String.valueOf(expressCondition.getCustomerId()));
        condition.setUpdated(now);
    }

    /**
     * @Description 退货换货
     * @author lining
     * @date 2019/1/11 11:24:15
     * @param expressInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveExpressForReturning(OrderExpressInfo expressInfo){
        this.validateReturning(expressInfo.getAfterSaleDetailId());
        String lockKey = CacheName.CACHE_KEY_RETURNING_AFTER_SALE + expressInfo.getAfterSaleDetailId();
        Lock lock = new RedisLock(cache, lockKey, ORDER_UPDATE_LOCK_EXPIRES_TIME);
        if (lock.tryLock()) {
            try {
                //保存物流信息
                expressInfoMapper.insertSelective(expressInfo);
                OrderAfterSaleDetail afterSaleDetail = new OrderAfterSaleDetail();
                this.dealOrderAfterSaleDetail(expressInfo,afterSaleDetail);
                //修改售后状态
                afterSaleDetailMapper.updateByPrimaryKeySelective(afterSaleDetail);
                try {
                    //订单日志
                    this.saveOrderLog(expressInfo);
                }catch (Exception e){
                    LOGGER.info("售后退货换货-日志异常,不回滚",e);
                }
            } finally {
                lock.unlock();
            }
        } else {
            throw new BusinessException(BusinessCode.CODE_440603);
        }
    }

    /**
     * @Description 验证是否可以输入快递信息（
     * @author lining
     * @date 2019/1/13 16:32:22
     * @param aftersaleDetailId
     * @return
     */
    private void validateReturning(Long aftersaleDetailId){
        //验证售后是否强制关闭
        orderAfterSaleDetailService.validateCloseAfterSaleStatus(aftersaleDetailId);
        OrderAfterSaleDetail detail = afterSaleDetailMapper.selectByPrimaryKey(aftersaleDetailId);
        OrderAfterSaleCondition condition = new OrderAfterSaleCondition();
        condition.setOrderNo(detail.getOrderNo());
        condition.setSkuId(detail.getSkuId());
        List<OrderExpressInfoVO> lst = expressInfoMapper.selectReturnOrderExpressInfoByCondition(condition);
        if(detail.getResultStatus().intValue() != AfterSaleAuditStatusEnum.YES.getTypeCode().intValue() ){
            LOGGER.error("售后状态错误,不能输入物流信息！！");
            throw new BusinessException(BusinessCode.CODE_440608);
        }
        if(!CollectionUtils.isEmpty(lst)){
            LOGGER.error("不能重复输入物流信息！！");
            throw new BusinessException(BusinessCode.CODE_440609);
        }
        if(detail.getAfterSaleStatus().intValue() == AfterSaleStatusEnum.CLOSED.getTypeCode().intValue()){
            LOGGER.error("会员超时未填写快递信息，售后订单自动关闭！！");
            throw new BusinessException(BusinessCode.CODE_440604);
        }
    }



    /**
     * @Description 退货换货订单日志
     * @author lining
     * @date 2019/1/13 14:32:33
     * @param expressInfo
     * @return
     */
    private void saveOrderLog(OrderExpressInfo expressInfo){
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectByPrimaryKey(expressInfo.getAfterSaleDetailId());
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNo(afterSaleDetail.getOrderNo());
        orderLog.setSkuId(afterSaleDetail.getSkuId());
        String pre="售后-";
        orderLog.setCreated(new Date());
        //退货
        if(expressInfo.getType().intValue() == RETURNING_TYPE){
            pre += AfterSaleViewStatusEnum.RETURNING.getTypeDesc();
        //换货
        }else if(expressInfo.getType().intValue() == EXCHANGE_TYPE){
            pre += AfterSaleViewStatusEnum.EXCHANGING.getTypeDesc();
        }
        String operationPropertity =pre.concat("【").concat(OrderAfterSaleTypeEnum.getDescByCode(afterSaleDetail.getAfterSaleType())).concat("】");
        orderLog.setOperationProperty(operationPropertity);
        orderLogMapper.insertSelective(orderLog);
    }

    private void dealOrderAfterSaleDetail(OrderExpressInfo expressInfo,OrderAfterSaleDetail afterSaleDetail){
        afterSaleDetail.setUpdated(expressInfo.getUpdated());
        afterSaleDetail.setUpdatedBy(expressInfo.getUpdatedBy());
        afterSaleDetail.setId(expressInfo.getAfterSaleDetailId());
        OrderAfterSaleDetail detail = afterSaleDetailMapper.selectByPrimaryKey(expressInfo.getAfterSaleDetailId());
        //退货
        if(detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode().intValue()
                || detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode().intValue() ){
            afterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.RETURNING.getTypeCode());
        //换货
        }else if(detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode().intValue()
                || detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode().intValue() ){
            afterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.EXCHANGING.getTypeCode());
        }else{
            LOGGER.info("物流状态错误！");
        }

    }

    /**
     * 构造换货日志信息
     * @param orderLog
     * @param condition
     */
    private void buildOrderLog(OrderLog orderLog,OrderExpressCondition condition){
        OrderAfterSaleDetail orderAfterSaleDetail = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getAfterSaleDetailId());
        Integer afterSaleType = orderAfterSaleDetail.getAfterSaleType();
        String operationPropertity = this.getOperationPropertityByRefund(afterSaleType);
        orderLog.setOrderNo(condition.getOrderNo());
        orderLog.setSkuId(condition.getSkuId());
        orderLog.setOperationProperty(operationPropertity);
        orderLog.setCreated(new Date());
    }

    /**
     * 保存日志
     * @return
     */
    private Boolean saveOrderLog(OrderLog orderLog){
        Integer res = orderLogMapper.insertSelective(orderLog);
        if(res < UPDATE_SUCCESS){
            return false;
        }
        return true;
    }

    /**
     * 获取售后换货操作类型
     * @param afterSaleType
     * @return
     */
    private String getOperationPropertityByRefund(Integer afterSaleType){
        switch (afterSaleType){
            case DELIVERED_EXCHANDE:
                return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_EXCHANGE_FINISH.getPropertyDes();
            case FINISHED_EXCHANDE:
                return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_EXCHANGE_FINISH.getPropertyDes();
            default:
                return "";
        }
    }

}
